var Protocol        =   require("../rpc-json/json-client");
var XError          =   require("../util/x-errors-const");
var RpcCallError    =   require("../util/rpc-call-error");
var XQueue          =   require("../util/xqueue");
var EndpointManager =   require("./endpointManager");

var CheckTimeoutInfo = function ()
{
    this.minTimeoutInvoke       = 2;        //计算的最小的超时次数, 默认2次(在checkTimeoutInterval时间内超过了minTimeoutInvoke, 才计算超时)
    this.checkTimeoutInterval   = 60000;    //统计时间间隔, (默认60s, 不能小于30s)
    this.frequenceFailInvoke    = 5;        //连续失败次数
    this.minFrequenceFailTime   = 5;        //
    this.radio                  = 0.5;      //超时比例 > 该值则认为超时了 (0.1 <= radio <= 1.0)
    this.tryTimeInterval        = 30000;    //重试时间间隔，单位毫秒
};

var ObjectProxy =   function() {
    this._objName   =   "";
    this._pTimeoutQueue =   new XQueue();
    this._manager   =   undefined;
    this._requestId =   1;
    this._iTimeout  =   3000;
    this._protocol  =   Protocol;
    this._communicator  =   undefined;
    this._checkTimeoutInfo  = new CheckTimeoutInfo();
}

module.exports  =   ObjectProxy;

ObjectProxy.prototype.__defineSetter__("communicator", function(value) { this._communicator = value; })
ObjectProxy.prototype.__defineGetter__("communicator", function() { return this._communicator; })

ObjectProxy.prototype.__defineGetter__("timeout", function() { return this._iTimeout; })
ObjectProxy.prototype.__defineSetter__("timeout", function(value) { this._iTimeout = value; })

ObjectProxy.prototype.__defineGetter__("name", function() { return this._objName; })
ObjectProxy.prototype.__defineSetter__("name", function(value) { this._objName = value; })

ObjectProxy.prototype.__defineGetter__("pTimeoutQueue", function() { return this._pTimeoutQueue; })
ObjectProxy.prototype.__defineSetter__("pTimeoutQueue", function(value) { this._pTimeoutQueue = value; })

ObjectProxy.prototype.initialize    =   function(ObjName, options) {
    this._manager = new EndpointManager(this, ObjName, options);
    this._objName = ObjName;
}

ObjectProxy.prototype.setProtocol   =   function(protocol) {
    this._protocol  =   protocol;
}

ObjectProxy.prototype.genRequestId  =   function() {
    return ++this._requestId;
}

ObjectProxy.prototype.setCheckTimeoutInfo = function (checkTimeoutInfo) {
    Object.assign(this._checkTimeoutInfo, checkTimeoutInfo);
}

ObjectProxy.prototype.doInvoke  =   function() {
    var self = this;
    self._pTimeoutQueue.forEach(function(key) {
        var reqMessage  =   self._pTimeoutQueue.pop(key, true);
        var adapter =   self._manager.selectAdapterProxy(reqMessage);
        if(adapter) {
            adapter.invoke(reqMessage);
        } else {
            self.doInvokeException(reqMessage);
        }
    })
}

ObjectProxy.prototype.doTimeout =   function(reqMessage) {
    this._pTimeoutQueue.erase(reqMessage.request.iRequestId);
    reqMessage.clearTimeout();
    reqMessage.promise.reject(new RpcCallError({request:reqMessage, response:undefined, error:{code:XError.CLIENT.REQUEST_TIMEOUT, message:"call remote server timeout(no adapter selected)"}}));
}

ObjectProxy.prototype.doInvokeException = function(reqMessage) {
    reqMessage.clearTimeout();
    reqMessage.promise.reject(new RpcCallError({request:reqMessage, response:undefined, error:{code:XError.SERVER.TARSADAPTERNULL, message:"select adapterProxy is null"}}));
}

ObjectProxy.prototype.invoke    = function(reqMessage) {
    var adapter = this._manager.selectAdapterProxy(reqMessage);
    if(adapter) {
        adapter.invoke(reqMessage);
    } else {
        var hashCode = reqMessage.request.property['hashCode'];
        var adapters =   this._manager.getAllAdapters() || [];
        if(!hashCode || adapters.length === 0) {
            this._pTimeoutQueue.push(reqMessage.request.iRequestId, reqMessage);
        }
    }

    return reqMessage.promise.promise;
}

ObjectProxy.prototype.destroy   =   function() {
    this._manager.destroy();
}